package org.example.utils;

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.security.SecureDigestAlgorithm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import javax.crypto.SecretKey;
import java.time.Instant;
import java.util.Date;
import java.util.UUID;

/**
 * @Description: token的制作和管理
 * @Author:曹震
 * @Date: 2024/11/23 12:25
 */
@PropertySource("classpath:key.properties")
public class JwtToken {
    private static String SECRET = "your-256-bit-secret-key-here-your-256-bit-secret-key-here";  // 给 SECRET 字段直接赋值

//    @Value("${TOKEN.KEY}")
//    public void setSecret(String secret) {
//        SECRET = secret;
//    }

    private final static SecureDigestAlgorithm<SecretKey ,SecretKey>ALGORITHM=Jwts.SIG.HS256;
    //秘钥实例
    public static final SecretKey KEY=Keys.hmacShaKeyFor(SECRET.getBytes());

    private static final long ACCESS_EXPIRE = 7*24*60*60*1000;  // 过期期限

    // 生成Token
    public static String createToken(String userId) {
        //令牌id
        String uuid= UUID.randomUUID().toString();
        Date exprireDate = Date.from(Instant.now().plusMillis(ACCESS_EXPIRE));
        return Jwts.builder()
                .header()
                .add("typ","JWT")
                .add("alg","HS256")
                .and()
                .claim("userId",userId)
                .id(uuid)
                .expiration(exprireDate)
                .issuedAt(new Date())
                .signWith(KEY,ALGORITHM)
                .compact();
    }

    // 验证 Token 是否有效
    public static boolean isTokenExpired(String token) {
        try {
            // 解析 Token
            Jws<Claims> jwsClaims = parseToken(token);
            Date expiration = jwsClaims.getPayload().getExpiration();  // 获取过期时间
            return expiration.before(new Date());  // 如果过期时间在当前时间之前，返回 true（已过期）
        } catch (ExpiredJwtException e) {
            // Token 已过期异常
            return true;
        } catch (Exception e) {
            // 其他异常（如无效 Token）处理
            e.printStackTrace();
            return true;  // 可以视为无效 Token，也当作过期处理
        }
    }

    // 解析 Token
   public static Jws<Claims> parseToken(String token){
        return Jwts.parser()
                .verifyWith(KEY)
                .build()
                .parseSignedClaims(token);
   }

    // 判断 Token 是否快要过期
    public static boolean isTokenExpiringSoon(Claims claims) {
        Date expirationDate = claims.getExpiration();
        long timeLeft = expirationDate.getTime() - System.currentTimeMillis();
        return timeLeft < 30*60*1000;  // 如果剩余时间小于 30 分钟，则视为即将过期
    }

    // 延长 Token 的过期时间
    public static String extendTokenExpiration( Claims claims) {
        // 获取原始的 Token 数据
        String username = claims.getSubject();
        long newExpirationTime = System.currentTimeMillis() + 3*24*60*60*1000;

        // 生成新的 Token，延长过期时间
        return Jwts.builder()
                .setSubject(username)
                .setIssuedAt(new Date())  // 设置为当前时间
                .setExpiration(new Date(newExpirationTime))  // 延长过期时间
                .signWith(KEY, ALGORITHM)
                .compact();
    }

    //校验token
    public static boolean validateToken(String token) {
        try {
            // 尝试解析Token并验证其有效性
            Jws<Claims> claims = parseToken(token);  // 解析Token
            return !isTokenExpired(token);  // 如果Token没有过期，返回true
        } catch (Exception e) {
            return false;  // 如果发生任何异常，表示Token无效
        }
    }

    // 从Token中获取 userId
    public static String getUserIdFromToken(String token) {
        try {
            Jws<Claims> claims = parseToken(token);
            return claims.getBody().get("userId", String.class);  // 获取userId
        } catch (Exception e) {
            return null;  // 如果解析失败或异常，返回null
        }
    }
}
